package com.zdp.leetcode;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class 按序打印 {
    /*
    * 题目描述：
    * 我们提供了一个类：

public class Foo {
  public void first() { print("first"); }
  public void second() { print("second"); }
  public void third() { print("third"); }
}
三个不同的线程将会共用一个 Foo 实例。

线程 A 将会调用 first() 方法
线程 B 将会调用 second() 方法
线程 C 将会调用 third() 方法
请设计修改程序，以确保 second() 方法在 first() 方法之后被执行，third() 方法在 second() 方法之后被执行。

 

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/print-in-order
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
    * */
}
class Foo {
//控制线程的执行顺序，一般可以使用信号量机制
    /*Semaphore two = new Semaphore(0);
    Semaphore three = new Semaphore(0);*/
    //用lock锁试试  ===>配condition 来实现精确唤醒
    Lock lock = new ReentrantLock();
    Condition second = lock.newCondition();
    Condition third = lock.newCondition();
    //也可以使用原子类型的int
    int num=1;
    public Foo() {

    }

    public void first(Runnable printFirst) throws InterruptedException {

        // printFirst.run() outputs "first". Do not change or remove this line.
        lock.lock();

        printFirst.run();
        num=2;
        second.signal();
        //two.release();
        lock.unlock();
    }

    public void second(Runnable printSecond) throws InterruptedException {
       // two.acquire();
        lock.lock();
        while(num!=2){
            second.await();
        }
        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        num=3;
        third.signal();
       // three.release();
        lock.unlock();
    }

    public void third(Runnable printThird) throws InterruptedException {
        lock.lock();
        //three.acquire();
        while(num!=3){
            third.await();
        }
        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        lock.unlock();
    }
}
